package cn.modoumama.excelUilt.po;

import cn.modoumama.common.tools.ObjectUtils;
import cn.modoumama.common.tools.StringUtils;
import cn.modoumama.excelUilt.common.InitCell;
import cn.modoumama.excelUilt.common.InitCellStyle;
import org.apache.poi.ss.usermodel.*;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class SheetEntity extends HashMap<Integer, Entry<String, CellEntity>> {
    private static final long serialVersionUID = 1L;
    
    /** 工作薄*/
    private Workbook workbook;
	/** 第几页 */
	private Integer index = 0;
	/** 页名 */
	private String name;
    /** 是否有带表描述*/
    private boolean tableDesc = false;
    /** 是否有带表头*/
    private boolean head = false;
    /** 表头的行数  */
    private Integer headRowNumber = 0;
    
    /** 从第几条开始读取 */
    private Integer first = 0;
    /**宽度*/
    private short width = 20;
    /**行高*/
    private short height = 24;
    /**默认时间格式 m/d/yy h:mm*/
    private String dateFormat = BuiltinFormats.getBuiltinFormat(22);

    /** 样式 */
	private Map<String, CellStyle> callStyles = new HashMap<>();

	/** 头部样式处理器 */
	private InitCellStyle headCellStyle;

	/** 列表样式处理器*/
	private InitCellStyle listCellStyle;

    /** 需要替换的模板数据 */
    private Object templateDate;
    /**当页的数据内容*/
    List<?> data;
    
    
    public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	public boolean isTableDesc() {
		return tableDesc;
	}

	public void setTableDesc(boolean tableDesc) {
		this.tableDesc = tableDesc;
	}

	public boolean isHead() {
		return head;
	}

	public void setHead(boolean head) {
		this.head = head;
	}
	
	/**
	 * 获取真实的数据表头行数，从0开始
	 * @return
	 */
	public Integer getHeadRowNumber() {
		if(isTableDesc() && headRowNumber == 0) {
			headRowNumber = 1;
		}
		return headRowNumber;
	}

	public void setHeadRowNumber(Integer headRowNumber) {
		head = true;
		if(headRowNumber > 0) {
			this.headRowNumber = 0;
		}
	}

	/**
	 * 获取真实的数据开始行数，从0开始
	 * @return
	 */
	public Integer getFirst() {
		if(first <= getHeadRowNumber()){
			first = getHeadRowNumber()+1;
		}else if(first > 2){
			return first;
		}else {
			int tmp = 0;
			if(isTableDesc()){
				tmp++;
			}
			if(isHead()) {
				tmp++;
			}
			first = tmp > first? tmp:first;
		}
		return first;
	}

	/**
	 * 设置行数按
	 * @param first
	 */
	public void setFirst(Integer first) {
		if(first > 0) {
			this.first = first;
		}
	}
	
	public Entry<String, CellEntity> put(Integer key, String field) {
		return put(key, field, null, null, null, null, null);
    }
	
	public Entry<String, CellEntity> put(Integer key, String field ,String desc) {
		return put(key, field, desc, null, null, null, null);
    }

	public Entry<String, CellEntity> put(Integer key, String field ,Integer width) {
		return put(key, field, null, width, null, null, null);
	}
	
	public Entry<String, CellEntity> put(Integer key, String field ,String desc ,Integer width) {
		return put(key, field, desc, width, null, null, null);
    }

	public Entry<String, CellEntity> put(Integer key, String field ,Integer width, String format) {
		return put(key, field, null, width, format, null, null);
	}

	public Entry<String, CellEntity> put(Integer key, String field , String desc, Integer width , String format) {
    	return put(key, field, desc, width, format, null, null);
    }
	
	public Entry<String, CellEntity> put(Integer key, String field,  InitCell initCell) {
		return put(key, field, null, null, null, null,initCell);
    }
	
	public Entry<String, CellEntity> put(Integer key, String field ,String desc,  InitCell initCell) {
		return put(key, field, desc, null, null, null,initCell);
    }
	
	public Entry<String, CellEntity> put(Integer key, String field ,Integer width,  InitCell initCell) {
		return put(key, field, null, width, null, null,initCell);
    }
	
	public Entry<String, CellEntity> put(Integer key, String field ,String desc ,Integer width,  InitCell initCell) {
		return put(key, field, desc, width, null, null,initCell);
    }

	public Entry<String, CellEntity> put(Integer key, String field , String desc, Integer width , String format,  InitCell initCell) {
    	return put(key, field, desc, width, format, null,initCell);
    }

	public Entry<String, CellEntity> put(Integer key, String field , String desc, Integer width , String format, Font font, InitCell initCell) {
		CellEntity cellEntry = new CellEntity(width,desc,format,font,initCell);
    	Entry<String, CellEntity> entry = new MethodEntry(field, cellEntry);
    	if(StringUtils.isNotBlank(desc)){
    		setHead(true);
    	}
    	return super.put(key, entry);
    }
    
    public String getField(Integer key){
    	return get(key).getKey();
    }
    
    public String getDesc(Integer key){
    	return get(key).getValue().getDesc();
    }
    
    public void rowHead(Row row){
    	for (Integer key : keySet()) {
    		Cell cell = row.createCell(key);
			setCell(cell, getDesc(key),true);
    	}
    }

	public void rowData(Row row, Object object){
		if(object != null){
			for (Integer key : keySet()) {
				String fieldName = getField(key);
				Object value = ObjectUtils.getValue(fieldName, object);
				try {
					Cell cell = row.createCell(key);
					setCell(cell, value, false);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
    }

    public void replaceTemplate(){
		if(templateDate != null) {
            // 生成一个表格
            Sheet sheet;
            //读取页
            if(StringUtils.isNotBlank(name)){
                sheet = workbook.getSheet(name);
            }else{
                sheet = workbook.getSheetAt(index);
            }
			// 读取行
			for (int rowNum = 0; rowNum <= sheet.getLastRowNum(); rowNum++) {
				Row row = sheet.getRow(rowNum);
				if (row != null) {
					for (int cellNum = 0; cellNum <= row.getLastCellNum(); cellNum++) {
						Cell cell = row.getCell(cellNum);
						if (cell != null) {
							String value = cell.getStringCellValue();
							if (StringUtils.isNotBlank(value)) {
								value = StringUtils.replace(value, templateDate);
								cell.setCellValue(value);
							}
						}
					}
				}
			}
		}
	}
    
    public void setCell(Cell cell,Object value,boolean isHead){
		if(isHead) {
			cell.setCellStyle(getCallStyle("head"));
		}else{
			CellEntity cellEntry = get(cell.getColumnIndex()).getValue();
			CellStyle cellStyle = cellEntry.getCellStyle();
			if (cellEntry.getInitCell() != null) {
				cellStyle = cellEntry.getInitCell().getCellStyle(value, cellStyle, this);

				value = cellEntry.getInitCell().getCallValue(cell, value);
			}
			cell.setCellStyle(cellStyle);
		}


    	Integer type = isPrimitive(value);

    	switch (type) {
    	case 1:
		case 2:
			Double val2 = new Double(value.toString());
    		cell.setCellValue(val2);
			break;
		case 3:
			Boolean val3 = (Boolean) value;
    		cell.setCellValue(val3);
			break;
		case 4:
			Date val4 = (Date) value;
    		cell.setCellValue(val4);
			break;
		case 5:
			String val5 = value.toString();
    		cell.setCellValue(val5);
			break;
		}
    }

    
    /**
     * @return 0.其他类型；1.基本类型；2.数字类型3.时间类型，4其他类型（转成字符串）
     */
    public static int isPrimitive(Object obj){
    	int flag = 0;
    	if(obj != null){
    		if(obj.getClass().isPrimitive()) {
        		flag = 1;
    		}else if(obj instanceof Integer 
        	   || obj instanceof Long
        	   || obj instanceof Byte 
        	   || obj instanceof Short 
        	   || obj instanceof Float 
        	   || obj instanceof Double
        	   || obj instanceof BigDecimal
        	){
        		flag = 2;
        	}else if( obj instanceof Boolean){
        		flag = 3;
        	}else if( obj instanceof Date){
        		flag = 4;
        	}else{
        		flag = 5;
        	}
    	}
    	return flag;
    }
    
    class MethodEntry implements Entry<String,CellEntity>{
    	/** 属性名*/
    	String field;
    	/** 属性描述*/
    	CellEntity cellEntry;
		/**
		 * @param field   属性名
		 * @param cellEntry    属性描述
		 */
		public MethodEntry(String field, CellEntity cellEntry){
			this.field = field;
			this.cellEntry = cellEntry;
		}
		
		@Override
		public String getKey() {
			return field;
		}
		@Override
		public CellEntity getValue() {
			return cellEntry;
		}
		@Override
		public CellEntity setValue(CellEntity cellEntry) {
			this.cellEntry = cellEntry;
			return cellEntry;
		}
    }

	public Integer getIndex() {
		return index;
	}

	public void setIndex(Integer index) {
		this.index = index;
	}

	public short getHeight() {
		return height;
	}

	public void setHeight(short height) {
		this.height = height;
	}

	public String getDateFormat() {
		return dateFormat;
	}

	public void setDateFormat(String dateFormat) {
		this.dateFormat = dateFormat;
	}

	public short getWidth() {
		return width;
	}

	public void setWidth(short width) {
		this.width = width;
	}
	
	public Workbook getWorkbook() {
		return workbook;
	}

	public void setWorkbook(Workbook workbook) {
		this.workbook = workbook;
	}

	public Object getTemplateDate() {
		return templateDate;
	}

	public void setTemplateDate(Object templateDate) {
		this.templateDate = templateDate;
	}

	public List<?> getData() {
		return data;
	}

	public void setData(List<?> data) {
		this.data = data;
	}

	public CellStyle getCallStyle(String key){
		return callStyles.get(key);
	}

	public void addCallStyles(String key, CellStyle cellStyle){
		callStyles.put(key, cellStyle);
	}

	public InitCellStyle getHeadCellStyle() {
		return headCellStyle;
	}

	public void setHeadCellStyle(InitCellStyle headCellStyle) {
		this.headCellStyle = headCellStyle;
	}

	public InitCellStyle getListCellStyle() {
		return listCellStyle;
	}

	public void setListCellStyle(InitCellStyle listCellStyle) {
		this.listCellStyle = listCellStyle;
	}

	@Override
    public SheetEntity clone() {  
	 SheetEntity sheetEneity = (SheetEntity)super.clone();  
        return sheetEneity;  
    }
}
